package com.smartwebx.fr.service;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Objects;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.primitives.Ints;
import com.smartwebx.fr.bean.FunParams;
import com.smartwebx.fr.bean.ProcResultUtil;
import com.smartwebx.fr.bean.SimpleUseArgConf;
import com.smartwebx.fr.bean.mysql.HaJssfk;
import com.smartwebx.fr.dao.StoredProcDao;
import com.smartwebx.fr.util.ParamSubsti;
import com.smartwebx.fr.util.StationFinalFields;

/**
 * 存储过程服务
 * 
 * @author XX
 * @param <T>
 * 
 */
@Service
public class StoredProcService {

	@Autowired
	private StoredProcDao storedProcDao;

	public ProcResultUtil getProTable(HaJssfk jsFun,
			Map<String, SimpleUseArgConf> paramNameUseArg) throws IOException {
		String funName = jsFun.getFunname();
		String funParams = jsFun.getFunparams();
		Integer returnType = jsFun.getFunreturntype();

		ObjectMapper mapper = new ObjectMapper();
		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
				false);

		List<FunParams> funParamMaps = mapper.readValue(funParams,
				new TypeReference<List<FunParams>>() {
				});

		ProcResultUtil procUtil = new ProcResultUtil();
		String callSql = "{? = call " + funName + "(";
		Map<String, String> paramNameType = Maps.newLinkedHashMap();
		int size = 1;
		for (FunParams paramMap : funParamMaps) {
			String dbType = paramMap.getDbtype();
			String name = paramMap.getName();
			paramNameType.put(name, dbType);

			callSql += (funParamMaps.size() == size) ? "?" : "?,";
			size++;
		}
		callSql += ")}";
		procUtil.setNameDbType(paramNameType);
		procUtil.setFunName(funName);
		procUtil.setReturnType(returnType);
		procUtil.setCallSql(callSql);
		procUtil.setHasHeader(true);

		storedProcDao.getProResult(procUtil, paramNameUseArg);

		return procUtil;
	}

	public String getSingleData(String callSql, List<SimpleUseArgConf> simpleUseArgs,
			String backType, String dataPoints) {
		List<List<String>> result = getResultBySqlAndPageParam(callSql,
				simpleUseArgs, backType, false);
		int leftP = 0, rightP = 0;
		if (!Strings.isNullOrEmpty(dataPoints)) {
			List<String> dataPointsList = Splitter.on(',').splitToList(
					dataPoints);
			if (dataPointsList.size() == 2) {
				leftP = Ints.tryParse(dataPointsList.get(0));
				rightP = Ints.tryParse(dataPointsList.get(1));
			}
		}
		List<String> lineDatas = Iterables.get(result, leftP, null);
		String point = null;
		if (lineDatas != null) {
			point = Iterables.get(lineDatas, rightP, null);
		}
		return point;
	}

	public String getSingleData(String callSql, List<SimpleUseArgConf> simpleUseArgs,
			String backType) {
		List<List<String>> result = getResultBySqlAndPageParam(callSql,
				simpleUseArgs, backType, false);
		String val = StationFinalFields.No_Data_Point;
		List<String> first = result.get(0);
		if (!first.isEmpty()) {
			if (!Strings.isNullOrEmpty(first.get(0))) {
				val = first.get(0);
			}
		}
		return val;
	}

	/**
	 * 
	 * <p>
	 * Title: getResultBySqlAndPageParam
	 * </p>
	 * <p>
	 * Description:
	 * </p>
	 * 
	 * @param callSql
	 * @param useArgConfs
	 * @param backType
	 *            table|signValue
	 * @return
	 */
	public List<List<String>> getResultBySqlAndPageParam(String callSql,
			List<SimpleUseArgConf> simpleUseArgs, String backType, boolean hasHeader) {
		List<String> paramNames = Lists.newArrayList();
		// 判断是sql语句还是存储过程
		String sqlType = null;
		String newSql = null;
		Entry<String, List<String>> sqlAndParams = null;
		if (StringUtils.indexOfIgnoreCase(callSql, "call") > -1) {
			sqlType = "proc";
			newSql = "{ ? = "
					+ ParamSubsti.pageParamReplaceByStr(callSql, simpleUseArgs)
					+ "}";
		} else if (StringUtils.indexOfIgnoreCase(callSql, "select") > -1) {
			sqlType = "sql";
			sqlAndParams = ParamSubsti.pageParamReplace(callSql, simpleUseArgs);
		}

		ProcResultUtil result = null;
		if (Objects.equal("proc", sqlType)) {
			result = storedProcDao.getResultByProc(newSql, backType,
					paramNames, hasHeader);
		} else if (Objects.equal("sql", sqlType)) {
			result = storedProcDao.getResultBySql(sqlAndParams, hasHeader);
		}

		return result.getResult();
	}

}
